"""
使用前几行模拟多级表头的实现
隐藏真实的 HeaderView，使用数据行模拟表头，实现多行多列合并效果
"""

from PySide6.QtWidgets import (
    QApplication, QMainWindow, QTableView, QVBoxLayout, 
    QWidget, QPushButton, QHBoxLayout
)
from PySide6.QtGui import QStandardItemModel, QStandardItem, QColor, QFont
from PySide6.QtCore import Qt
import sys


class SimulatedHeaderTableView(QTableView):
    """使用前几行模拟表头的 TableView"""
    
    def __init__(self, header_row_count=3, parent=None):
        super().__init__(parent)
        self.header_row_count = header_row_count  # 模拟表头的行数
        self._resizing_column = -1  # 正在调整的列
        self._resize_start_x = 0  # 开始调整时的X坐标
        self._resize_start_width = 0  # 开始调整时的列宽
        
        # 隐藏默认表头
        self.horizontalHeader().hide()
        self.verticalHeader().hide()
        
        # 禁用选中模拟表头行
        self.setSelectionBehavior(QTableView.SelectionBehavior.SelectRows)
        
        # 启用鼠标追踪以便检测列边界
        self.setMouseTracking(True)
    
    def mousePressEvent(self, event):
        """鼠标按下事件：开始调整列宽"""
        if event.button() == Qt.MouseButton.LeftButton:
            col = self._get_resize_column(event.pos())
            if col >= 0:
                self._resizing_column = col
                self._resize_start_x = event.globalPosition().x()
                self._resize_start_width = self.columnWidth(col)
                event.accept()
                return
        super().mousePressEvent(event)
    
    def mouseMoveEvent(self, event):
        """鼠标移动事件：调整列宽或更改光标"""
        if self._resizing_column >= 0:
            # 正在调整列宽
            delta = event.globalPosition().x() - self._resize_start_x
            new_width = max(20, self._resize_start_width + int(delta))  # 最小20像素
            self.setColumnWidth(self._resizing_column, new_width)
            event.accept()
            return
        else:
            # 检测是否在列边界，更改光标
            col = self._get_resize_column(event.pos())
            if col >= 0:
                self.setCursor(Qt.CursorShape.SplitHCursor)
            else:
                self.setCursor(Qt.CursorShape.ArrowCursor)
        
        super().mouseMoveEvent(event)
    
    def mouseReleaseEvent(self, event):
        """鼠标释放事件：结束调整"""
        if event.button() == Qt.MouseButton.LeftButton and self._resizing_column >= 0:
            self._resizing_column = -1
            self.setCursor(Qt.CursorShape.ArrowCursor)
            event.accept()
            return
        super().mouseReleaseEvent(event)
    
    def _get_resize_column(self, pos):
        """检测鼠标位置是否在列边界，返回列索引"""
        tolerance = 5  # 边界容差（5像素）
        x = pos.x()
        
        # 检测所有列的右边界
        for col in range(self.model().columnCount()):
            col_x = self.columnViewportPosition(col) + self.columnWidth(col)
            if abs(x - col_x) <= tolerance:
                return col
        
        return -1
    
    def selectionChanged(self, selected, deselected):
        """重写选择改变事件，禁止选择表头行"""
        super().selectionChanged(selected, deselected)
        
        # 取消对表头行的选择
        selection = self.selectionModel()
        for row in range(self.header_row_count):
            for col in range(self.model().columnCount()):
                index = self.model().index(row, col)
                if selection.isSelected(index):
                    selection.select(index, selection.SelectionFlag.Deselect)


class SimHeaderDemo(QMainWindow):
    """模拟表头演示主窗口"""
    
    def __init__(self):
        super().__init__()
        self.header_row_count = 3  # 前3行作为表头
        self.init_ui()
        self.setup_model()
        self.setup_simulated_header()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle('模拟多级表头示例')
        self.setGeometry(100, 100, 900, 600)
        
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        
        # 按钮工具栏
        toolbar = QHBoxLayout()
        
        self.btn_add = QPushButton('添加数据行')
        self.btn_add.clicked.connect(self.add_data_row)
        toolbar.addWidget(self.btn_add)
        
        self.btn_delete = QPushButton('删除数据行')
        self.btn_delete.clicked.connect(self.delete_data_row)
        toolbar.addWidget(self.btn_delete)
        
        self.btn_clear = QPushButton('清空数据')
        self.btn_clear.clicked.connect(self.clear_data)
        toolbar.addWidget(self.btn_clear)
        
        toolbar.addStretch()
        layout.addLayout(toolbar)
        
        # 使用自定义 TableView
        self.table_view = SimulatedHeaderTableView(self.header_row_count)
        self.table_view.setAlternatingRowColors(True)
        layout.addWidget(self.table_view)
    
    def setup_model(self):
        """设置数据模型"""
        self.model = QStandardItemModel(0, 9)
        self.table_view.setModel(self.model)
    
    def setup_simulated_header(self):
        """设置模拟表头（前3行）"""
        # 定义三级表头结构
        # 格式：[(文本, 起始列, 跨列数, 行索引), ...]
        header_cells = [
            # 第1层（第0行）
            ('基本信息', 0, 3, 0),
            ('成绩', 3, 6, 0),
            # 第2层（第1行）
            ('个人', 0, 1, 1),
            ('基础', 1, 2, 1),
            ('文科', 3, 3, 1),
            ('理科', 6, 3, 1),
            # 第3层（第2行）
            ('姓名', 0, 1, 2),
            ('性别', 1, 1, 2),
            ('年龄', 2, 1, 2),
            ('语文', 3, 1, 2),
            ('数学', 4, 1, 2),
            ('英语', 5, 1, 2),
            ('物理', 6, 1, 2),
            ('化学', 7, 1, 2),
            ('生物', 8, 1, 2),
        ]
        
        # 创建表头行
        for _ in range(self.header_row_count):
            row_items = []
            for col in range(9):
                item = QStandardItem('')
                # 设置表头样式
                item.setBackground(QColor(240, 240, 240))
                font = QFont()
                font.setBold(True)
                item.setFont(font)
                item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                item.setFlags(Qt.ItemFlag.ItemIsEnabled)  # 禁用编辑
                row_items.append(item)
            self.model.appendRow(row_items)
        
        # 设置单元格内容和合并
        for text, col_start, col_span, row_idx in header_cells:
            item = self.model.item(row_idx, col_start)
            item.setText(text)
            
            # 设置合并
            if col_span > 1:
                self.table_view.setSpan(row_idx, col_start, 1, col_span)
        
        # 添加示例数据
        self._add_data_rows_internal([
            ['张三', '男', '18', '85', '90', '88', '92', '87', '89'],
            ['李四', '女', '17', '92', '88', '91', '85', '90', '88'],
            ['王五', '男', '18', '78', '85', '82', '88', '84', '86'],
            ['赵六', '女', '17', '88', '92', '90', '91', '89', '92'],
            ['孙七', '男', '18', '90', '87', '89', '86', '88', '85'],
        ])
        
        # 调整列宽
        self.table_view.resizeColumnsToContents()
        
        self.statusBar().showMessage(f'模拟表头已设置（前{self.header_row_count}行），当前数据行：5行，在列边界拖动调整列宽')
    
    def _add_data_rows_internal(self, data_list):
        """内部方法：添加数据行"""
        for row_data in data_list:
            row_items = []
            for value in row_data:
                item = QStandardItem(value)
                item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
                row_items.append(item)
            self.model.appendRow(row_items)
    
    def add_data_row(self):
        """添加数据行（不影响表头行）"""
        # 示例数据
        new_data = ['新学生', '男', '18', '80', '85', '88', '90', '87', '89']
        
        row_items = []
        for value in new_data:
            item = QStandardItem(value)
            item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
            row_items.append(item)
        
        # 直接添加到模型末尾（表头行在前面，不受影响）
        self.model.appendRow(row_items)
        
        data_row_count = self.model.rowCount() - self.header_row_count
        self.statusBar().showMessage(f'已添加数据行，当前数据行：{data_row_count}行')
    
    def delete_data_row(self):
        """删除最后一行数据（不影响表头行）"""
        total_rows = self.model.rowCount()
        
        # 确保不删除表头行
        if total_rows > self.header_row_count:
            self.model.removeRow(total_rows - 1)
            data_row_count = self.model.rowCount() - self.header_row_count
            self.statusBar().showMessage(f'已删除最后一行，当前数据行：{data_row_count}行')
        else:
            self.statusBar().showMessage('没有数据行可删除（仅剩表头行）')
    
    def clear_data(self):
        """清空所有数据行（保留表头行）"""
        total_rows = self.model.rowCount()
        
        # 从后往前删除，避免索引变化
        for row in range(total_rows - 1, self.header_row_count - 1, -1):
            self.model.removeRow(row)
        
        self.statusBar().showMessage('已清空所有数据行，表头行保留')
    
    def get_data_rows(self):
        """获取所有数据行（排除表头行）"""
        data_rows = []
        for row in range(self.header_row_count, self.model.rowCount()):
            row_data = []
            for col in range(self.model.columnCount()):
                item = self.model.item(row, col)
                row_data.append(item.text() if item else '')
            data_rows.append(row_data)
        return data_rows


def main():
    """主函数"""
    app = QApplication(sys.argv)
    window = SimHeaderDemo()
    window.show()
    sys.exit(app.exec())


if __name__ == '__main__':
    main()
